package components.contorls.superClass
{
    import components.core.IViewport;
    import components.core.ScrollPolicy;
    import components.core.UIComponent;
    import components.core.zn_internal;
    import components.events.ScrollBarEvent;
    import components.events.ViewPortMaxSizeChangeEvent;
    import components.utils.EventListenerUtil;
    import components.utils.TimeoutIntervalUtil;
    
    import flash.display.DisplayObject;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.utils.clearInterval;
    import flash.utils.clearTimeout;
    import flash.utils.setInterval;
    import flash.utils.setTimeout;
    
    import mx.events.ResizeEvent;

    [Event(name="updateParmComplete", type="components.events.ScrollBarEvent")]
    [Event(name="visibleChange", type="components.events.ScrollBarEvent")]
    public class BaseScrollBar extends UIComponent
    {
        protected static const MIN_THUMB_SIZE:Number = 14;

        protected static const MAX_STEP:Number = 5;

        private var _viewportName:String;

        private var _viewport:IViewport;

        /**
         *每次滚动值
         */
        public var step:Number = MAX_STEP;

        private var _maxValue:Number;

        /**
         *viewPort界面的滚动比例
         * 如果ScrollBar滚动1像素，viewPort则需要滚动1*_viewStepScale像素
         */
        private var _viewStepScale:Number;

        /**
         *scrollBar的滚动比例
         *  如果viewPort滚动1像素，scrollBar则需要滚动1*_stepScale像素
         */
        zn_internal var stepScale:Number;

        private var _scrollPolicy:String = "off";

        private var _value:Number = 0;

        /**
         *按钮按下不放时，自动滚动延迟函数监听ID
         */
        protected var _timeOutID:int = 0;

        private var _scrollIntervalID:int = 0;

        /**
         *鼠标在轨道上按下时，计算出来的目标值
         */
        protected var _targetValue:Number = 0;

        /**
         *thumb相对于trackMC的点击坐标 ，用于计算拖动偏移
         */
        private var _oldThumbMouseDownPos:Number;

        /**
         *相对于thumb自己的点击坐标
         * 如果鼠标拖动出thumb外后，再拖回来时，的起始拖动坐标
         */
        private var _oldThumbMousePos:Number;

        private var _autoScroll:Boolean = false;

        public function BaseScrollBar()
        {
            super();

			EventListenerUtil.addEventListener(upButton,MouseEvent.MOUSE_DOWN, upButton_mouseDownHandler);
			EventListenerUtil.addEventListener(upButton,MouseEvent.MOUSE_UP, cleanTween);
			EventListenerUtil.addEventListener(upButton,MouseEvent.ROLL_OUT, cleanTween);

			EventListenerUtil.addEventListener(downButton,MouseEvent.MOUSE_DOWN, downButton_mouseDownHandler);
			EventListenerUtil.addEventListener(downButton,MouseEvent.MOUSE_UP, cleanTween);
			EventListenerUtil.addEventListener(downButton,MouseEvent.ROLL_OUT, cleanTween);

			EventListenerUtil.addEventListener(trackMC,MouseEvent.MOUSE_DOWN, trackMC_mouseDownHandler);
			EventListenerUtil.addEventListener(trackMC,MouseEvent.MOUSE_UP, cleanTween);
			EventListenerUtil.addEventListener(trackMC,MouseEvent.ROLL_OUT, cleanTween);

			EventListenerUtil.addEventListener(thumbButton,MouseEvent.MOUSE_DOWN, thumbButton_MouseDownHandler);
			thumbButton.isScale=true;
        }

        /***************************************
         *
         * 显示对象声明
         *
         * **************************************/

        public function get upButton():BaseButton
        {
            return getChildByName("upButtonSkin") as BaseButton;
        }

        public function get downButton():BaseButton
        {
            return getChildByName("downButtonSkin") as BaseButton;
        }

        public function get trackMC():MovieClip
        {
            return getChildByName("trackSkin") as MovieClip;
        }

        public function get thumbButton():BaseButton
        {
            return getChildByName("thumbButtonSkin") as BaseButton;
        }

        /***************************************
         *
         * 验证
         *
         * **************************************/

        protected override function commitProperties():void
        {
            super.commitProperties();

            if (this is BaseVScrollBar)
            {
                thumbButton.y = value + trackMC.y;
            }
            else
            {
                thumbButton.x = value + trackMC.x;
            }
        }

        protected override function measureSizes():Boolean
        {
            var change:Boolean = super.measureSizes();
            if (change)
            {
                if (this is BaseVScrollBar)
                {
                    trackMC.y = upButton.height;
                    trackMC.height = height - upButton.height - downButton.height;
                    downButton.y = height - downButton.height;
                }
                else
                {
                    trackMC.x = upButton.width;
                    trackMC.width = width - upButton.width - downButton.width;
                    downButton.x = width - downButton.width;
                }
                updateScrollParm();
            }

            return change;
        }


        protected override function updateDisplayList():void
        {
            super.updateDisplayList();

            correctThumb();

            if (scrollPolicy == ScrollPolicy.AUTO)
            {
                if (_maxValue > 0)
                    visible = true;
                else
                    visible = false;
            }
            else if (scrollPolicy == ScrollPolicy.ON)
                visible = true;
            else
                visible = false;
        }

        /***************************************
         *
         * 组件定义
         *
         * **************************************/

        [Inspectable(defaultValue="")]
        public function get viewportName():String
        {
            return _viewportName;
        }

        public function set viewportName(value:String):void
        {
            _viewportName = value;

            if (value != "" && parent && parent.hasOwnProperty(viewportName))
            {
                var display:DisplayObject = parent.getChildByName(viewportName);
                if (display is IViewport)
                    viewport = display as IViewport;
            }
        }

        [Inspectable(type="List", enumeration="auto,on,off", defaultValue="off")]
        public function get scrollPolicy():String
        {
            return _scrollPolicy;
        }

        public function set scrollPolicy(value:String):void
        {
            _scrollPolicy = value;

            invalidate();
        }

        [Inspectable(defaultValue="false")]
        public function get autoScroll():Boolean
        {
            return _autoScroll;
        }

        public function set autoScroll(value:Boolean):void
        {
            _autoScroll = value;
        }

        /***************************************
         *
         * 其他代码
         *
         * **************************************/

        public function get viewport():IViewport
        {
            return _viewport;
        }

        public function set viewport(value:IViewport):void
        {
            if (_viewport)
            {
                _viewport.removeEventListener(ResizeEvent.RESIZE, viewPort_resizeHandler);

                if (this is BaseVScrollBar)
                    _viewport.removeEventListener(ViewPortMaxSizeChangeEvent.MAX_HEIGHT_CHANGE, viewPort_resizeHandler);
                else
                    _viewport.removeEventListener(ViewPortMaxSizeChangeEvent.MAX_WIDTH_CHANGE, viewPort_resizeHandler);
            }
            _viewport = value;

            if (_viewport)
            {
                _viewport.addEventListener(ResizeEvent.RESIZE, viewPort_resizeHandler, false, 0, true);

                if (this is BaseVScrollBar)
                    _viewport.addEventListener(ViewPortMaxSizeChangeEvent.MAX_HEIGHT_CHANGE, viewPort_resizeHandler, false, 0, true);
                else
                    _viewport.addEventListener(ViewPortMaxSizeChangeEvent.MAX_WIDTH_CHANGE, viewPort_resizeHandler, false, 0, true);
            }

            updateScrollParm();
            invalidate();
        }

        protected function viewPort_resizeHandler(event:Event):void
        {
            updateScrollParm();
            invalidate();
        }

        protected function updateScrollParm():void
        {
            if (!viewport)
                return;

            var maxPositon:Number;
            var thumbSize:Number;
            var contentSize:Number;
            var maxSize:Number;
            var trackSize:Number;

            if (this is BaseVScrollBar)
            {
                maxPositon = viewport.maxVerticalScrollPosition;
                contentSize = viewport.contentHeight;
                maxSize = viewport.maxHeight;
                trackSize = trackMC.height;
            }
            else
            {
                maxPositon = viewport.maxHorizontalScrollPosition;
                contentSize = viewport.contentWidth;
                maxSize = viewport.maxWidth;
                trackSize = trackMC.width;
            }

            /*计算滚动参数*/
            if (maxPositon > 0)
            {
                thumbSize = contentSize / maxSize * trackSize;

                if (thumbSize < MIN_THUMB_SIZE)
                    thumbSize = MIN_THUMB_SIZE;

                _maxValue = trackSize - thumbSize;

                _viewStepScale = maxPositon / _maxValue;
                zn_internal::stepScale = 1 / _viewStepScale;
            }
            else
            {
                thumbSize = 0;
                _maxValue = 0;
                _viewStepScale = 0;
                zn_internal::stepScale = 0;
            }

            /*赋值*/
            if (this is BaseVScrollBar)
            {
                thumbButton.height = thumbSize;
            }
            else
            {
                thumbButton.width = thumbSize;
            }

            if (value > _maxValue)
                value = _maxValue;

            if (autoScroll)
                value = _maxValue;

            dispatchEvent(new ScrollBarEvent(ScrollBarEvent.UPDATE_PARM_COMPLETE));
        }

        public function get value():Number
        {
            return _value;
        }

        public function set value(v:Number):void
        {
            v = Math.max(v, 0);
            v = Math.min(v, _maxValue);

            _value = v;

            /*滚动viewPort对象*/
            if (!viewport)
                return;

            if (this is BaseVScrollBar)
            {
                viewport.verticalScrollPosition = _value * _viewStepScale;
            }
            else
            {
                viewport.horizontalScrollPosition = _value * _viewStepScale;
            }

            invalidate();
        }

        /**
         *验证ThumbButton
         *
         */
        protected function correctThumb():void
        {
            var thumbSize:Number;
            var thumbPoint:Number;
            var trackBottom:Number;

            if (this is BaseVScrollBar)
            {
                thumbSize = thumbButton.height;
                thumbPoint = thumbButton.y;
                trackBottom = height - downButton.height;
            }
            else
            {
                thumbSize = thumbButton.width;
                thumbPoint = thumbButton.x;
                trackBottom = width - downButton.width;
            }

            if (thumbPoint < 0)
                thumbPoint = 0;
            else if (thumbPoint + thumbSize > trackBottom)
                thumbPoint = trackBottom - thumbSize;

            if (this is BaseVScrollBar)
            {
                thumbButton.y = thumbPoint;
            }
            else
            {
                thumbButton.x = thumbPoint;
            }
        }

        protected function upButton_mouseDownHandler(event:MouseEvent):void
        {
            value -= step;
            _timeOutID = TimeoutIntervalUtil.addSetTimeout(this,btnTween, _delayTime, false);
        }

        protected function downButton_mouseDownHandler(event:MouseEvent):void
        {
            value += step;
            _timeOutID = TimeoutIntervalUtil.addSetTimeout(this,btnTween, _delayTime, true);
        }

        /**
         *
         * @param flag true:向下滚动，false:向上滚动
         *
         */
        protected function btnTween(flag:Boolean):void
        {
            clearTimeout(_timeOutID);
            _scrollIntervalID = TimeoutIntervalUtil.addSetInterval(this,scrollBtnDown, 50, flag);
        }

        protected function scrollBtnDown(flag:Boolean):void
        {
            if (flag)
                value += step;
            else
                value -= step;

            if (value == 0 || value == _maxValue)
                clearInterval(_scrollIntervalID);
        }

        protected function cleanTween(event:MouseEvent):void
        {
            clearInterval(_scrollIntervalID);
            clearTimeout(_timeOutID);
        }

        protected function trackMC_mouseDownHandler(event:Event):void
        {
            _targetValue = trackMousePostion;
            _targetValue = Math.round(_targetValue / step) * step;

            scrollTrackDown();
            _timeOutID = TimeoutIntervalUtil.addSetTimeout(this,trackDownTween, _delayTime);
        }

        protected function trackDownTween():void
        {
            clearTimeout(_timeOutID);
            _scrollIntervalID = TimeoutIntervalUtil.addSetInterval(this,scrollTrackDown, 50);
        }

        protected function scrollTrackDown():void
        {
            if (Math.round(value) == Math.round(_targetValue))
                return;
            if (value == _targetValue)
                clearInterval(_scrollIntervalID);
            else
                scrollToTarget();
        }

        protected function scrollToTarget():void
        {
            if (value < _targetValue)
                value += step;
            else if (value > _targetValue)
                value -= step;
        }

        protected function get trackMousePostion():Number
        {
            if (this is BaseVScrollBar)
            {
                return trackMC.mouseY * trackMC.scaleY;
            }
            else
            {
                return trackMC.mouseX * trackMC.scaleX;
            }
        }

        protected function get thumbMousePostion():Number
        {
            if (this is BaseVScrollBar)
            {
                return thumbButton.mouseY;
            }
            else
            {
                return thumbButton.mouseX;
            }
        }

        protected function thumbButton_MouseDownHandler(event:MouseEvent):void
        {
            stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
            stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);

            _oldThumbMouseDownPos = trackMousePostion;
            _oldThumbMousePos = thumbMousePostion;
        }

        protected function stage_mouseMoveHandler(event:Event):void
        {
            var dis:Number = trackMousePostion - _oldThumbMouseDownPos;

            value += dis;

            if (value == 0)
                _oldThumbMouseDownPos = _oldThumbMousePos;
            else if (value == _maxValue)
            {
                if (this is BaseVScrollBar)
                {
                    _oldThumbMouseDownPos = trackMC.height - thumbButton.height + _oldThumbMousePos;
                }
                else
                {
                    _oldThumbMouseDownPos = trackMC.width - thumbButton.width + _oldThumbMousePos;
                }
            }
            else
                _oldThumbMouseDownPos = trackMousePostion;
        }

        protected function stage_mouseUpHandler(event:Event):void
        {
            if (stage)
                stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
        }

        public override function set visible(value:Boolean):void
        {
            if (super.visible == value)
                return;

            super.visible = value;
            dispatchEvent(new ScrollBarEvent(ScrollBarEvent.VISIBLE_CHANGE));
        }

        public override function set focusComp(value:UIComponent):void
        {
            super.focusComp = value;

            upButton.focusComp = focusComp;
            downButton.focusComp = focusComp;
            thumbButton.focusComp = focusComp;
        }

        public override function destroy():void
        {
            super.destroy();
            _viewportName = null;
            _viewport = null;
            _scrollPolicy = null;

        }
    }
}